﻿(*
 * Author : Peter Lisovin (peter@lisovin.com)
 * Date   : 2012
 *) 
namespace Toolkit.Collections

open System
open System.Collections
open System.Collections.Generic
open System.Collections.Specialized
open System.Runtime.InteropServices

type OrderedDictionary<'TKey, 'TValue when 'TKey : equality and 'TValue : equality>() as this =
    inherit OrderedDictionary()
    
    let thisDict = this :> IDictionary<_,_>

    interface IDictionary<'TKey, 'TValue> with
        member x.Item 
            with get(key) = 
                if x.ContainsKey(key) 
                then base.[key] :?> 'TValue
                else KeyNotFoundException("The given key was not present in the dictionary.") |> raise
            and set key value = 
                base.[key] <- value
        member x.Keys with get() = base.Keys |> Seq.cast<'TKey> |> Seq.toArray :> ICollection<_>
        member x.Values with get() = base.Values |> Seq.cast<'TValue> |> Seq.toArray :> ICollection<_>
        member x.Add(key, value) = base.Add(key, value)
        member x.ContainsKey(key) = base.Contains(key)
        member x.TryGetValue(key, value) = 
            if x.Contains(key)
            then value <- x.[key]; true
            else false
        member x.Remove(key) = base.Remove(key); true
    
    interface ICollection<KeyValuePair<'TKey,'TValue>> with
        member x.Count with get() = base.Count
        member x.IsReadOnly with get() = base.IsReadOnly
        member x.Add(entry) = base.Add(entry.Key, entry.Value)
        member x.Clear() = base.Clear()
        member x.Contains(entry) = this |> Seq.cast<DictionaryEntry> |> Seq.exists (fun e -> entry.Key.Equals(e.Key) && entry.Value.Equals(e.Value))
        member x.CopyTo(array, index) = base.CopyTo(array, index)
        member x.Remove(entry) = thisDict.Remove(entry.Key) 

    interface IEnumerable<KeyValuePair<'TKey,'TValue>> with
        member x.GetEnumerator() = 
            let kvs = (this :> IDictionary<_,_>).Keys |> Seq.map (fun key -> KeyValuePair<'TKey, 'TValue>(key, (this :> IDictionary<_,_>).[key]))
            kvs.GetEnumerator()
      
    member this.Item with get(key) = thisDict.[key] and set key value = thisDict.[key] <- value
    member this.Keys with get() = thisDict.Keys
    member this.Values with get() = thisDict.Values
    member this.Add(key, value) = thisDict.Add(key, value)
    member this.ContainsKey(key) = thisDict.ContainsKey(key)
    member this.TryGetValue(key, [<Out>] value : 'TValue byref) = thisDict.TryGetValue(key, &value)
    member this.Remove(key : 'TKey) = thisDict.Remove(key)
    member this.GetEnumerator() = (this :> IEnumerable<KeyValuePair<'TKey,'TValue>>).GetEnumerator()



